﻿Imports System.Text

Module ModTool
    Public gASCII As Encoding = Encoding.ASCII 'ASCII编码
    Public gEncDefault As Encoding = Encoding.Default '默认编码
    Private mHexDigits() As Byte = gASCII.GetBytes("0123456789ABCDEF") '字节转十六进制时十六进制字符串代码表
    Private mByteDigits() As Byte '十六进制转字节，十六进制每个字符对应的码值表

    ''' <summary>
    ''' 字节数组转长整形
    ''' </summary>
    ''' <param name="b">字节数组 1-8个元素</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function BytesToLong(ByVal b() As Byte) As UInt64
        Dim lValue As UInt64 = 0
        Dim i As Byte
        If b.Length > 8 Then Return 0
        If b.Length = 0 Then Return 0


        For i = 0 To b.GetUpperBound(0)
            lValue = lValue + b(i)
            If Not i = b.GetUpperBound(0) Then
                lValue = lValue << 8
            End If
        Next

        Return lValue
    End Function

    ''' <summary>
    ''' 将长整形转为字节数组
    ''' </summary>
    ''' <param name="lValue"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function LongToBytes(ByVal lValue As UInt64) As Byte()
        Dim b(7) As Byte
        For i = 7 To 0 Step -1
            b(i) = lValue And 255

            lValue = lValue >> 8
            If lValue = 0 Then Exit For
        Next

        Return b
    End Function

    ''' <summary>
    ''' 字节转十六进制
    ''' </summary>
    ''' <param name="bData"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToHex(ByVal bData() As Byte) As String
        ByteToHex = ByteToHex(bData, 0, bData.Length)
    End Function


    ''' <summary>
    ''' 字节转十六进制
    ''' </summary>
    ''' <param name="bData"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToHex(ByVal bData() As Byte, ByVal iOffset As Integer, ByVal iCount As Integer) As String
        Dim bHex() As Byte
        Dim i As Long, lIndex As Long
        Dim iEndIndex = iOffset + iCount - 1
        If bData.Length = 0 Then Return String.Empty
        If bData.Length <= iEndIndex Then Return String.Empty
        '初始化操作
        ReDim bHex((iCount - 1) * 2 + 1)

        '开始转换
        lIndex = 0
        For i = iOffset To iEndIndex
            bHex(lIndex) = mHexDigits(bData(i) \ 16) : lIndex = lIndex + 1
            bHex(lIndex) = mHexDigits(bData(i) Mod 16) : lIndex = lIndex + 1
        Next

        ByteToHex = gASCII.GetString(bHex)
    End Function



    Private Sub CheckHexDigit()
        '初始化操作
        If mByteDigits Is Nothing Then
            Dim bTmp() As Byte
            ReDim mByteDigits(255)
            bTmp = gASCII.GetBytes("0123456789ABCDEF")
            For i = 0 To UBound(bTmp)
                mByteDigits(bTmp(i)) = i
            Next
            bTmp = gASCII.GetBytes("abcdef")
            For i = 0 To UBound(bTmp)
                mByteDigits(bTmp(i)) = i + 10
            Next
        End If
    End Sub

    ''' <summary>
    ''' 十六进制转字节
    ''' </summary>
    ''' <param name="sHex"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function HexToByte(ByVal sHex As String) As Byte()
        '十六进制转字节
        Dim i As Long
        Dim bbuf() As Byte
        ReDim bbuf(0)

        If Len(sHex) Mod 2 = 1 Then
            sHex = "0" & sHex
        End If

        If Len(sHex) = 0 Then
            Return bbuf
        End If

        CheckHexDigit()

        '开始转换
        bbuf = gASCII.GetBytes(sHex)
        Dim iData As Byte, lIndex As Long
        Dim bRtn() As Byte
        ReDim bRtn((UBound(bbuf) - 1) / 2)

        lIndex = 0
        For i = 0 To UBound(bbuf)
            iData = mByteDigits(bbuf(i)) * 16 '高位
            i = i + 1
            iData = iData + mByteDigits(bbuf(i)) '低位
            bRtn(lIndex) = iData
            lIndex = lIndex + 1
        Next
        HexToByte = bRtn
    End Function

    Public Function HexToByte(ByVal sHex As String, ByVal buf As BufferChunk) As BufferChunk
        '十六进制转字节
        Dim i As Long


        If Len(sHex) Mod 2 = 1 Then
            sHex = "0" & sHex
        End If

        If Len(sHex) = 0 Then
            Return buf
        End If

        CheckHexDigit()

        '开始转换
        Dim bbuf = gASCII.GetBytes(sHex)
        Dim iData As Byte, lIndex As Long

        lIndex = 0
        For i = 0 To UBound(bbuf)
            iData = mByteDigits(bbuf(i)) * 16 '高位
            i = i + 1
            iData = iData + mByteDigits(bbuf(i)) '低位
            buf.WriteByte(iData)
            lIndex = lIndex + 1
        Next
        Return buf
    End Function


    ''' <summary>
    ''' 字节转Bit
    ''' </summary>
    ''' <param name="iNum"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToBit(ByVal iNum As Byte) As Byte()
        Dim bList As BitArray = New BitArray({iNum})
        Dim iBit(7) As Byte, iIndex As Byte = 0

        For Each bValue As Boolean In bList
            iBit(iIndex) = IIf(bValue, 1, 0)

            iIndex += 1
        Next

        Return iBit
    End Function

    ''' <summary>
    ''' Bit转字节
    ''' </summary>
    ''' <param name="iBits">存储位数据的8元素数组</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function BitToByte(ByVal iBits() As Byte) As Byte
        Dim bList As BitArray = New BitArray(8)
        Dim iValue() As Byte = {0}
        For i As Byte = 0 To 7
            bList(i) = IIf(iBits(i) = 0, False, True)
        Next
        '将bit数组转换为字节
        bList.CopyTo(iValue, 0)
        Return iValue(0)
    End Function

    ''' <summary>
    ''' 字节转BCD码
    ''' </summary>
    ''' <param name="iNum"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToBCDNUM(ByVal iNum As Byte) As Byte
        Return Byte.Parse(iNum.ToString, Globalization.NumberStyles.HexNumber)
    End Function

    ''' <summary>
    ''' 字节转BCD码
    ''' </summary>
    ''' <param name="iNum"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToBCDNUM(ByVal iNum() As Byte) As Byte()
        For i As Integer = 0 To iNum.Length - 1
            iNum(i) = Byte.Parse(iNum(i).ToString, Globalization.NumberStyles.HexNumber)
        Next
        Return iNum
    End Function

    ''' <summary>
    ''' BCD转字节值
    ''' </summary>
    ''' <param name="iNum"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function BCDToByte(ByVal iNum As Byte) As Byte
        Return Byte.Parse(Convert.ToString(iNum, 16))
    End Function

    ''' <summary>
    ''' BCD转字节值
    ''' </summary>
    ''' <param name="iNum"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function BCDToByte(ByVal iNum() As Byte) As Byte()
        Dim bHex As String = String.Empty
        For i As Integer = 0 To iNum.Length - 1
            'If iNum(i) <= &H99 Then
            bHex = Convert.ToString(iNum(i), 16)
            If IsNumeric(bHex) Then
                iNum(i) = Byte.Parse(bHex)
            Else
                iNum(i) = 0
            End If

            'End If
        Next
        Return iNum
    End Function

    ''' <summary>
    ''' 字节数组转短整型 Int16 高位在前
    ''' </summary>
    ''' <param name="bData"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToInt16(ByVal bData() As Byte) As UShort
        Return bData(1) + CInt(bData(0)) * 256
    End Function

    ''' <summary>
    ''' 字节数组转 Int32 整形 高位在前
    ''' </summary>
    ''' <param name="bData"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ByteToInt32(ByVal bData() As Byte) As UInt32
        Dim iValue As UInt32 = 0
        For i As Byte = 0 To bData.Length - 1
            iValue = iValue << 8
            iValue += bData(i)
            If i = 3 Then Exit For
        Next
        Return iValue
    End Function

    ''' <summary>
    ''' Int32 整形 转 字节数组 高位在前
    ''' </summary>
    ''' <param name="iValue"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Int32ToByte(ByVal iValue As UInt32) As Byte()
        Return copyOfRange(LongToBytes(iValue), 4, 4)
    End Function

    ''' <summary>
    ''' Int16 整形 转 字节数组  高位在前
    ''' </summary>
    ''' <param name="iValue"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Int16ToByte(ByVal iValue As UInt16) As Byte()
        Return copyOfRange(LongToBytes(iValue), 6, 2)
    End Function


    ''' <summary>
    ''' 拷贝数组
    ''' </summary>
    ''' <param name="src"></param>
    ''' <param name="iBegin"></param>
    ''' <param name="lLen"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function copyOfRange(ByVal src() As Byte, ByVal iBegin As Integer, ByVal lLen As Integer) As Byte()
        Return Arrays(Of Byte).copyOfRange(src, iBegin, lLen)
    End Function


    ''' <summary>
    ''' 检查字符串是否为指定长度
    ''' </summary>
    ''' <param name="sValue">待检查字符串</param>
    ''' <param name="iLength">需要的长度</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CheckStringLen(ByVal sValue As String, ByVal iLength As Integer, Optional ByVal sNullString As String = " ") As String
        If (String.Equals(sValue, String.Empty)) Then
            sValue = New String(sNullString, iLength)
        End If
        If sValue.Length > iLength Then
            sValue = sValue.Substring(0, iLength)
        End If
        If sValue.Length < iLength Then
            sValue = sValue & New String(sNullString, iLength - sValue.Length)
        End If
        Return sValue
    End Function

    ''' <summary>
    ''' 检查字符串是否为十六进制
    ''' </summary>
    ''' <param name="sValue">待检查字符串</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CheckIsHex(ByVal sValue As String) As Boolean
        If String.IsNullOrWhiteSpace(sValue) Then
            Return False
        End If
        Dim sHexChars = "0123456789ABCDEFabcdef"
        Dim iLen = sValue.Length
        For index = 0 To iLen - 1
            Dim sTmp = sValue.Substring(index, 1)
            If sHexChars.IndexOf(sTmp) = -1 Then
                Return False
            End If
        Next
        Return True
    End Function


    Public Function ReplaceEx(ByVal sSur As String, ByVal sValue() As String) As String
        Return ReplaceEx(sSur, "%1,%2,%3,%4,%5,%6,%7,%8,%9,%A,%B,%C,%D,%E,%F,%G,%H,%I,%J,%K,%L,%M,%N,%O,%P,%Q,%R,%S,%T,%U,%V,%W,%X,%Y,%Z", sValue)
    End Function

    Public Function ReplaceEx(ByVal sSur As String, ByVal sExKeyList As String, ByVal sValue() As String) As String
        Dim i As Long
        Dim sExKey() As String
        sExKey = Split(sExKeyList, ",")

        For i = 0 To sValue.GetUpperBound(0)
            If i > sExKey.GetUpperBound(0) Then Exit For
            sSur = sSur.Replace(sExKey(i), sValue(i))
        Next
        Return sSur
    End Function

End Module


Public Class Arrays(Of T)
    ''' <summary>
    ''' 拷贝数组
    ''' </summary>
    ''' <param name="src"></param>
    ''' <param name="iBegin"></param>
    ''' <param name="lLen"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function copyOfRange(ByVal src() As T, ByVal iBegin As Integer, ByVal lLen As Integer) As T()
        Dim bTmp() As T
        ReDim bTmp(lLen - 1)
        Array.Copy(src, iBegin, bTmp, 0, lLen)
        Return bTmp
    End Function
End Class
